import { HttpClient, HttpParams } from '@angular/common/http';
import { map, Observable } from 'rxjs';

import { NzSafeAny } from 'ng-zorro-antd/core/types';

import { Pagable, Page } from '../model';

export abstract class BaseHttpService<T> {
  constructor(protected http: HttpClient) {}

  protected abstract createModel(o: any): T;

  protected _update = (url: string, body?: any, queryParams?: any): Observable<any> => {
    return this.http.put<any>(url, body, { params: this._parseParams(queryParams) });
  };

  protected _save = (url: string, body?: any, queryParams?: any): Observable<string> => {
    return this.http.post<string>(url, body, { params: this._parseParams(queryParams) });
  };

  protected _delete = (url: string, queryParams?: any): Observable<any> => {
    return this.http.delete(url, { params: this._parseParams(queryParams) });
  };

  protected _getOne = (url: string, queryParams?: any): Observable<T> => {
    return this.http.get<T>(url, { params: this._parseParams(queryParams) }).pipe(map(data => this.createModel(data)));
  };

  protected _getList = (url: string, queryParams?: any): Observable<T[]> => {
    return this.http
      .get<T[]>(url, { params: this._parseParams(queryParams) })
      .pipe(map(data => data.map(e => this.createModel(e))));
  };

  protected _getPage = (url: string, pagable: Pagable, queryParams?: any): Observable<Page<T>> => {
    const params = { ...queryParams, ...{ page: pagable.page - 1, size: pagable.size, sort: pagable.sort } };
    return this.http.get<Page<T>>(url, { params: this._parseParams(params) }).pipe(
      map(data => {
        if (data && data.content) {
          data.content = data.content.map(e => this.createModel(e));
        }
        return data;
      })
    );
  };

  protected _parseParams = (params: NzSafeAny): HttpParams => {
    if (params) {
      params = {};
    }
    if (params instanceof HttpParams) {
      return params;
    }

    const newParams: NzSafeAny = {};
    Object.keys(params).forEach(key => {
      let _data = params[key];
      // 忽略空值
      if (_data == null) return;
      // 将时间转化为：时间戳 (秒)
      if (_data instanceof Date) {
        _data = _data.valueOf();
      }
      newParams[key] = _data;
    });
    return new HttpParams({ fromObject: newParams });
  };
}
